package com.lgp.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.log4j.Logger;

/**
 * 
 * @Title: HttpClientUtils.java
 * @Description: HttpClient工具类
 * @version V1.0
 */
public class HttpClientUtils {
    private static final Logger logger = Logger.getLogger(HttpClientUtils.class);

    public static final String METHOD_GET = "GET";

    public static final String METHOD_POST = "POST";

    public static final String DEFAULT_CHARSET = "UTF-8";

    public static final int defaultConnectionTimeout = 8000;// 连接超时时间

    public static final int defaultSoTimeout = 30000;// 回应超时时间

    /**
     * post请求
     * 
     * @param url
     * @param paramMap
     * @return
     */
    public static String sendPostRequest(String url, Map<String, String> paramMap,boolean isPolicy,String ip,Integer port) {
        logger.info("进行查询参数为：");
        logger.info("url：" + url);
        StringBuffer sb = new StringBuffer();
        Iterator iter = paramMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            String key = entry.getKey().toString();
            String val = paramMap.get(key);
            sb.append("名称 : " + key + " , 值 ：" + val + "; ");
        }
        logger.info(sb.toString());
        return sendHttpRequest(url, paramMap, METHOD_POST, "UTF-8", null, null,isPolicy,ip,port);
    }

    /**
     * get请求
     * 
     * @param url
     * @param paramMap
     * @return
     */
    public static String sendGetRequest(String url,boolean isPolicy,String ip,Integer port) {
        return sendHttpRequest(url, null, METHOD_GET, "UTF-8", null, null,isPolicy,ip,port);
    }

    /**
     * http请求
     * 
     * @param url
     * @param paramMap
     * @param http_method
     * @param charset
     * @param timeout
     * @return
     */
    public static String sendHttpRequest(String url, Map<String, String> paramMap, String http_method,
            String charset, Integer connectionTimeout, Integer soTimeout,boolean isPolicy,String ip,Integer port) {

        HttpMethod method = null;
        String responseString = "";

        HttpClient httpclient = new HttpClient();
        // 设置代理服务器的ip地址和端口
        if(isPolicy){
        	httpclient.getHostConfiguration().setProxy(ip, port);
            httpclient.getParams().setAuthenticationPreemptive(true);
            
//        	HttpHost proxy = new HttpHost(ip, port);
//        	httpclient.getHostConfiguration().setProxy(ip, port);
        	System.out.println("已设置代理ip");
        }
        // 使用抢先认证
        httpclient.getParams().setAuthenticationPreemptive(true);
        // 编码
        charset = charset == null ? DEFAULT_CHARSET : charset;
        connectionTimeout = connectionTimeout == null ? defaultConnectionTimeout : connectionTimeout;
        soTimeout = soTimeout == null ? defaultSoTimeout : soTimeout;
        // 设置连接超时时间
        httpclient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
        // 设置回应超时
        httpclient.getHttpConnectionManager().getParams().setSoTimeout(soTimeout);

        // get模式
        if (HttpClientUtils.METHOD_GET.equalsIgnoreCase(http_method)) {
            // 将url后面的参数分离出来，设置到queryString
            Map<String, String> urlMap = splitUrlAndQueryString(url);
            method = new GetMethod(urlMap.get("url"));
            method.getParams().setCredentialCharset(charset);
            if (urlMap.size() > 1) {
                if (null == paramMap) {
                    paramMap = new HashMap<String, String>();
                }
                for (Map.Entry<String, String> entry : urlMap.entrySet()) {
                    if (!"url".equals(entry.getKey())) {// 过滤掉url
                        paramMap.put(entry.getKey(), entry.getValue());
                    }
                }
            }
            if (null != paramMap) {
                String queryString = createLinkString(paramMap);
                method.setQueryString(queryString);
            }

        } else {
            // post
            method = new PostMethod(url);
            if (null != paramMap) {
                NameValuePair[] parameters = generatNameValuePair(paramMap);
                ((PostMethod) method).addParameters(parameters);
            }
            method.addRequestHeader("Content-Type", "application/x-www-form-urlencoded; text/html; charset="
                    + charset);
            method.addRequestHeader("Host", "www.snowsx.com");
        }
        method.addRequestHeader("User-Agent", "Mozilla/4.0");

        try {
            httpclient.executeMethod(method);
            // responseString = method.getResponseBodyAsString();

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    method.getResponseBodyAsStream(), charset));
            StringBuffer stringBuffer = new StringBuffer();
            String str = null;
            while ((str = reader.readLine()) != null) {
                stringBuffer.append(str);
            }
            responseString = stringBuffer.toString();
        } catch (HttpException e) {
            logger.error("访问远程服务器异常：<{}>, {}", e);
            // e.printStackTrace();
        } catch (IOException e) {
            logger.error("访问远程服务器发生读取IO异常：<{}>, {}", e);
            // e.printStackTrace();
        } finally {
            method.releaseConnection();
        }
        // logger.info("访问远程服务器<" + url + ">返回：" + responseString);
        return responseString;
    }

    public static String sendHttpRequestByProxy(String url, Map<String, String> paramMap, String http_method,
            String charset, Integer connectionTimeout, Integer soTimeout, String ip, Integer port) {

        HttpMethod method = null;
        String responseString = "";

        HttpClient httpclient = new HttpClient();
        // 设置代理服务器的ip地址和端口
        // httpclient.getHostConfiguration().setProxy("192.168.63.158", 54691);
        // 使用抢先认证
        httpclient.getParams().setAuthenticationPreemptive(true);
        // 编码
        charset = charset == null ? DEFAULT_CHARSET : charset;
        connectionTimeout = connectionTimeout == null ? defaultConnectionTimeout : connectionTimeout;
        soTimeout = soTimeout == null ? defaultSoTimeout : soTimeout;
        // 设置连接超时时间
        httpclient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
        // 设置回应超时
        httpclient.getHttpConnectionManager().getParams().setSoTimeout(soTimeout);

        // 此部分上线须删掉
//         HttpHost proxy = new HttpHost(ip,port);
//         httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

//         RequestConfig.Builder requestConfig = RequestConfig.custom().setSocketTimeout(10000)
// 				.setConnectTimeout(1000).setConnectionRequestTimeout(1000).setCookieSpec("ignoreCookies");
//         requestConfig.setProxy(proxy);
         
        httpclient.getHostConfiguration().setProxy(ip, port);
        httpclient.getParams().setAuthenticationPreemptive(true);

        // get模式
        if (HttpClientUtils.METHOD_GET.equalsIgnoreCase(http_method)) {
            // 将url后面的参数分离出来，设置到queryString
            Map<String, String> urlMap = splitUrlAndQueryString(url);
            method = new GetMethod(urlMap.get("url"));
            method.getParams().setCredentialCharset(charset);
            if (urlMap.size() > 1) {
                if (null == paramMap) {
                    paramMap = new HashMap<String, String>();
                }
                for (Map.Entry<String, String> entry : urlMap.entrySet()) {
                    if (!"url".equals(entry.getKey())) {// 过滤掉url
                        paramMap.put(entry.getKey(), entry.getValue());
                    }
                }
            }
            if (null != paramMap) {
                String queryString = createLinkString(paramMap);
                method.setQueryString(queryString);
            }

        } else {
            // post
            method = new PostMethod(url);
            if (null != paramMap) {
                NameValuePair[] parameters = generatNameValuePair(paramMap);
                ((PostMethod) method).addParameters(parameters);
            }
            method.addRequestHeader("Content-Type", "application/x-www-form-urlencoded; text/html; charset="
                    + charset);
            //AJAX
//            method.addRequestHeader("x-requested-with", "XMLHttpRequest");
            method.addRequestHeader("Host", "www.snowsx.com");
        }
        method.addRequestHeader("User-Agent", "Mozilla/4.0");

        try {
            httpclient.executeMethod(method);
            // responseString = method.getResponseBodyAsString();

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    method.getResponseBodyAsStream(), charset));
            StringBuffer stringBuffer = new StringBuffer();
            String str = null;
            while ((str = reader.readLine()) != null) {
                stringBuffer.append(str);
            }
            responseString = stringBuffer.toString();
        } catch (HttpException e) {
            logger.error("访问远程服务器异常：<{}>, {}", e);
            responseString = null;
            // e.printStackTrace();
        } catch (IOException e) {
            logger.error("访问远程服务器发生读取IO异常：<{}>, {}", e);
            responseString = null;
            // e.printStackTrace();
        } catch (Exception e) {
			logger.error("未知异常：<{}>, {}", e);
		}finally {
            method.releaseConnection();
        }
        // logger.info("访问远程服务器<" + url + ">返回：" + responseString);
        return responseString;
    }

    /**
     * 分割URL
     * 
     * @param url
     * @return
     */
    public static Map<String, String> splitUrlAndQueryString(String url) {
        Map<String, String> map = new HashMap<String, String>();

        if (url.indexOf("?") != -1) {
            map.put("url", url.split("\\?")[0]);
            String queryString = url.split("\\?")[1];
            String[] aParam = queryString.split("&");
            for (String param : aParam) {
                String[] e = param.split("=");
                if (e != null && e.length > 1) {
                    map.put(e[0], e[1]);
                }
            }
        } else {
            map.put("url", url);
        }

        return map;
    }

    /**
     * MAP类型数组转换成NameValuePair类型
     * 
     * @param properties MAP类型数组
     * @return NameValuePair类型数组
     */
    public static NameValuePair[] generatNameValuePair(Map<String, String> paramMap) {
        NameValuePair[] nameValuePair = new NameValuePair[paramMap.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            nameValuePair[i++] = new NameValuePair(entry.getKey(), entry.getValue());
        }
        return nameValuePair;
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     * 
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {

        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        String prestr = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = urlEncode(params.get(key), DEFAULT_CHARSET);

            if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }

        return prestr;
    }

    /**
     * @Title: createNoLinkString
     * @Description:
     * @param @param params
     * @param @return
     * @return String
     * @throws
     */
    public static String createNoLinkString(Map<String, String> params) {

        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        String prestr = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);

            if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }

        return prestr;

    }

    public static String urlEncode(String str, String charset) {
        try {
            charset = null == charset ? DEFAULT_CHARSET : charset;
            return URLEncoder.encode(str, charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String urlDecode(String str, String charset) {
        try {
            charset = null == charset ? DEFAULT_CHARSET : charset;
            return URLDecoder.decode(str, charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    
    public static String  downloadPage(String httpUrl) {
		StringBuffer pageBuffer = new StringBuffer();
		URL pageUrl =  null;
		Proxy proxy = null;
		try {
			pageUrl = new URL(httpUrl);;
			proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("220.185.197.231", 8998));

			// Open connection to URL for reading.
			BufferedReader reader = new BufferedReader(new InputStreamReader(pageUrl.openStream(), "utf-8"));
			// Read page into buffer.
			String line;
			
			while ((line = reader.readLine()) != null) {
				pageBuffer.append(line);
			}
			System.out.println(pageBuffer.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return pageBuffer.toString();
	}
}
